package com.common.frame.utils


import kotlinx.coroutines.*
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*


object TimeUtil {

    private val DEFAULT_DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd-HH mm:ss")
    private val COMMON_DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd HH:mm")
    private val DEFAULT_DATE_FORFILENAME = SimpleDateFormat("yyyy-MM-dd_HH_mm_ss")
    private val DEFAULT_FILENAME_FROM_TIME = SimpleDateFormat("yyyyMMddHHmmss")
    private val DATE_FORMAT_DATE = SimpleDateFormat("yyyy-MM-dd")
    private val DEFAULT_FORMAT by lazy { SimpleDateFormat("yyyy-MM-dd HH:mm:ss") }

    /**
     * long time to string
     *
     * @param timeInMillis timeInMillis
     * @param dateFormat   dateFormat
     * @return String
     */
    @JvmOverloads
    fun getTime(timeInMillis: Long, dateFormat: SimpleDateFormat = DEFAULT_DATE_FORMAT): String {
        return dateFormat.format(Date(timeInMillis))
    }

    fun getDateDay(milliseconds: Long): String {
        return DATE_FORMAT_DATE.format(Date(milliseconds))
    }

    /**
     * get current time in milliseconds
     *
     * @return long
     */
    val currentTimeInLong: Long
        get() = System.currentTimeMillis()

    /**
     * get current time in milliseconds, format is [.DEFAULT_DATE_FORMAT]
     *
     * @return String
     */
    val currentTimeInString: String
        get() = getTime(currentTimeInLong)

    /**
     * get current time in milliseconds
     *
     * @param dateFormat dateFormat
     * @return String
     */
    fun getCurrentTimeInString(dateFormat: SimpleDateFormat): String {

        return getTime(currentTimeInLong, dateFormat)
    }


    /**
     * get current time in milliseconds for file name
     *
     * @return String
     */
    val currentTimeForFileName: String
        get() = getTime(
            System.currentTimeMillis(),
            DEFAULT_DATE_FORFILENAME
        ) + "-" + (1 + Math.random() * 100).toInt()

    val currentTimeForSaveFileName: String
        get() = getTime(
            System.currentTimeMillis(),
            DEFAULT_FILENAME_FROM_TIME
        ) + (1 + Math.random() * 100).toInt()

    /**
     * 将毫秒数格式化为"##:##"的时间
     *
     * @param milliseconds 毫秒数
     * @return ##:##
     */
    fun formatTime(milliseconds: Long): String {
        if (milliseconds <= 0 || milliseconds >= 24 * 60 * 60 * 1000) {
            return "00:00"
        }
        val totalSeconds = (milliseconds / 1000).toInt()
        val seconds = totalSeconds % 60
        val minutes = totalSeconds / 60 % 60
        val hours = totalSeconds / 3600
        val stringBuilder = StringBuilder()
        val mFormatter =
            Formatter(stringBuilder, Locale.getDefault())
        return if (hours > 0) {
            mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString()
        } else {
            mFormatter.format("%02d:%02d", minutes, seconds).toString()
        }
    }

    fun formatTimeS(seconds: Long): String {
        val sb = StringBuffer()
        if (seconds < 60) {
            if (seconds < 10) {
                sb.append("00").append(":").append("0").append(seconds)
            } else {
                sb.append("00").append(":").append(seconds)
            }
        } else {
            if (seconds / 60 < 10) {
                if (seconds % 60 < 10) {
                    sb.append("0").append(seconds / 60).append(":").append("0").append(seconds % 60)
                } else {
                    sb.append("0").append(seconds / 60).append(":").append(seconds % 60)
                }
            } else {
                if (seconds % 60 < 10) {
                    sb.append(seconds / 60).append(":").append("0").append(seconds % 60)
                } else {
                    sb.append(seconds / 60).append(":").append(seconds % 60)
                }
            }
        }
        return sb.toString()
    }

    /**
     * 计时器
     * @param total 秒数
     */
    fun countDown(
        total: Long,
        onTick: ((Long) -> Unit)? = null,
        onFinish: (() -> Unit)? = null,
        scope: CoroutineScope = GlobalScope
    ): Job {
        return flow {
            for (i in total downTo 0) {
                emit(i)
                delay(1000)
            }
        }.flowOn(Dispatchers.Default)
            .onEach {
                if (it == 0L) {
                    onFinish?.invoke()
                } else {
                    onTick?.invoke(it)
                }
            }
            .flowOn(Dispatchers.Main)
            .launchIn(scope)
    }

    //轮询器
    fun interval(
        delay: Long = 1000L,
        onInterval: (() -> Unit)? = null,
        scope: CoroutineScope = GlobalScope
    ): Job {
        return flow {
            while (true) {
                emit(true)
                delay(delay)
            }
        }.flowOn(Dispatchers.Default)
            .onEach {
                onInterval?.invoke()
            }
            .flowOn(Dispatchers.Main)
            .launchIn(scope)
    }


    /**
     * 判断是否今天
     *
     * @param millis 毫秒时间戳
     * @return `true`: 是<br></br>`false`: 否
     */
    fun isToday(millis: Long): Boolean {
        return getDateDay(System.currentTimeMillis()) == getDateDay(millis)
    }

    /**
     * 将06-06 12:25转换成时间戳
     * @param date
     * @return
     */
    fun getTimestamp(date: String): Long {
        val c = Calendar.getInstance()
        val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm")
        val time = c[Calendar.YEAR].toString() + "-" + date
        try {
            return simpleDateFormat.parse(time).time
        } catch (e: ParseException) {
            e.printStackTrace()
        }
        return -1
    }

    fun stringToTimestamp(date: String, dateFormat: SimpleDateFormat = COMMON_DATE_FORMAT): Long {
        try {
            return dateFormat.parse(date).time
        } catch (e1: ParseException) {
            e1.printStackTrace()
        }

        return 0
    }

    fun getTimeDifference(date: String): Int {
        // 计算的时间差
        val df = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
        val currentTime = Date()
        val d1 = df.parse(df.format(currentTime))
        val d2 = df.parse(date)
        val differ = d2.time - d1.time
        return if (differ > 0) {
            (differ / (1000 * 3600 * 24)).toInt()
        } else {
            -1
        }
    }

    /**
     * 字符串转成时间戳
     */
    fun stringToMillis(time: String?): Long {
        try {
            return time?.let { DEFAULT_FORMAT.parse(it)?.time ?: -1 } ?: -1
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return -1
    }

    fun fixNum(num: Long): String {
        return when (num) {
            0L -> "00"
            in 1..9 -> "0$num"
            else -> num.toString()
        }
    }
}
